﻿using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Windows;
using System;
using System.Drawing;
using System.Linq;
using Buffer = SharpDX.Direct3D11.Buffer;
using Device = SharpDX.Direct3D11.Device;
using Resource = SharpDX.Direct3D11.Resource;
using Rectangle = System.Drawing.Rectangle;
using Color = System.Drawing.Color;

namespace MikadoShooter
{
    public static partial class GameHelper
    {
        public static void SetRenderTarget(Device device, SwapChain swapChain, RenderForm form)
        {
            device.ImmediateContext.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));

            using (Resource res = Resource.FromSwapChain<Texture2D>(swapChain, 0))
            {
                using (RenderTargetView view = new RenderTargetView(device, res))
                {
                    device.ImmediateContext.OutputMerger.SetTargets(view);
                }
            }

            BlendStateDescription blend = new BlendStateDescription();
            blend.RenderTarget[0] = new RenderTargetBlendDescription
            {
                IsBlendEnabled = true,
                SourceBlend = BlendOption.SourceAlpha,
                DestinationBlend = BlendOption.InverseSourceAlpha,
                BlendOperation = BlendOperation.Add,
                SourceAlphaBlend = BlendOption.One,
                DestinationAlphaBlend = BlendOption.Zero,
                AlphaBlendOperation = BlendOperation.Add,
                RenderTargetWriteMask = ColorWriteMaskFlags.All,
            };

            using (BlendState blendState = new BlendState(device, blend))
            {
                device.ImmediateContext.OutputMerger.SetBlendState(blendState, new Color4(1.0f), -1);
            }
        }

        public static byte[] RenderString(string text,RenderForm form)
        {
            Bitmap bitmap = new Bitmap(form.ClientSize.Width, form.ClientSize.Height);
            Graphics draw = Graphics.FromImage(bitmap);
            StringFormat stringFormat = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
            Rectangle box = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

            for (int i = 32; i < 512; i += 8)
            {
                Font font = new Font("Arial", i);
                SizeF size;
                if ((size = draw.MeasureString(text, font, form.ClientSize.Width, stringFormat)).Width >= (float)form.ClientSize.Width / 2)
                {
                    draw.DrawRectangle(new Pen(Color.Red, 3), (form.ClientSize.Width - size.Width) / 2, (form.ClientSize.Height - size.Height) / 2, size.Width, size.Height);
                    draw.DrawRectangle(new Pen(Color.DarkRed, 1), (form.ClientSize.Width - size.Width) / 2, (form.ClientSize.Height - size.Height) / 2, size.Width, size.Height);

                    draw.FillRectangle(Brushes.Black, (form.ClientSize.Width - size.Width + 3) / 2, (form.ClientSize.Height - size.Height + 3) / 2, size.Width - 3, size.Height - 3);
                    draw.DrawString(text, font, Brushes.White, box, stringFormat);
                    break;
                }
            }

            return (byte[])new ImageConverter().ConvertTo(bitmap, typeof(byte[]));
        }

        public static RenderTargetView GetTargetView(Device device)
        {
            RenderTargetView[] render = device.ImmediateContext.OutputMerger.GetRenderTargets(1);

            if (render != null && render.Length >= 1)
                return render.FirstOrDefault();

            throw new ApplicationException("Can´t get targetview");
        }

        public static string GetGpuName(SwapChain swapChain)
        {
            string gpuname = "Unknown GPU";

            using (Factory factory = swapChain.GetParent<Factory>())
            {
                if (factory.GetAdapterCount() > 0)
                {
                    using (Adapter adapter = factory.GetAdapter(0))
                    {
                        if (adapter != null)
                            gpuname = adapter.Description.Description;
                    }
                }
            }

            return gpuname;
        }

        public static Buffer GetBuffer(Device device, int sizeInBytes)
        {
            return new Buffer(device, new BufferDescription
            {
                BindFlags = BindFlags.ConstantBuffer,
                CpuAccessFlags = CpuAccessFlags.Write,
                SizeInBytes = sizeInBytes,
                Usage = ResourceUsage.Dynamic
            });
        }

        public static Buffer GetTextureBuffer(Device device)
        {
            return Buffer.Create(device, BindFlags.VertexBuffer, new[]
            {
                new Vector4(1.0f, -1.0f, 0.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 0.0f),
                new Vector4(-1.0f, -1.0f, 0.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 0.0f),
                new Vector4(1.0f, 1.0f, 0.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 0.0f),
                new Vector4(-1.0f, 1.0f, 0.0f, 1.0f), new Vector4(0.0f, 0.0f, 0.0f, 0.0f)
            });
        }
    }
}